package org.kernely.stream.persistence;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import org.hibernate.annotations.Cascade;
import org.kernely.security.persistence.User;

/**
 * Messages are short messages written by users or bundles.
 * Each message is contained in a stream
 */
@Entity
@Table(name="kernely_message")
//@NamedQuery (name = "getUserMessages",
//			query = "")
public class Message {
	public final static int MESSAGE_LENGTH = 140;
	
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name="message_id")
	/**
	 * Message's id
	 */
	private int id;
	
	/**
	 * Message's content
	 */
	private String content;
	
	/**
	 * Message's cache content (parsed urls...)
	 */
	private String contentCache;
	
	/**
	 * @return the contentCache
	 */
	public String getContentCache() {
		return contentCache;
	}

	/**
	 * @param contentCache the contentCache to set
	 */
	public void setContentCache(String contentCache) {
		this.contentCache = contentCache;
	}

	/**
	 * Message's date
	 */
	private Date date;
	
	private int commentable;
	
	/**
	 * @return the commentable
	 */
	public int getCommentable() {
		return commentable;
	}

	/**
	 * @param commentable the commentable to set
	 */
	public void setCommentable(int commentable) {
		this.commentable = commentable;
	}

	@ManyToOne
	@JoinColumn(name="fk_user_id")
	private User user;
	
	@ManyToOne
	@JoinColumn(name="fk_stream_id")
	private Stream stream;

	/**
	 * Users who added the message to their favorites
	 */
	@ManyToMany(cascade={CascadeType.MERGE}, fetch=FetchType.LAZY)
	@JoinTable( name="kernely_user_favorites",
				joinColumns=@JoinColumn(name="fk_message"),
				inverseJoinColumns=@JoinColumn(name="fk_user"))
	private Set<User> favoriteUsers;
	
	/**
	 * Constructor which fill the message with default values.
	 */
	public Message(){
		this.commentable = 0;
		this.comments = new HashSet<Message>();
		this.content = "";
		this.date = new Date();
		this.favoriteUsers = new HashSet<User>();
		this.id= 0;
		this.message = null;
		this.stream = new Stream();
		this.user = new User();
	}
	
	/**
	 * @return the stream
	 */
	public final Stream getStream() {
		return stream;
	}

	/**
	 * @param stream the stream to set
	 */
	public final void setStream(Stream stream) {
		this.stream = stream;
	}

	/**
	 * @return the id
	 */
	public final int getId() {
		return id;
	}

	/**
	 * @param id the id to set
	 */
	public final void setId(int id) {
		this.id = id;
	}

	/**
	 * @return the content
	 */
	public final String getContent() {
		return content;
	}

	/**
	 * @param content the content to set
	 */
	public final void setContent(String content) {
		this.content = content;
	}

	/**
	 * @return the user
	 */
	public final User getUser() {
		return user;
	}

	/**
	 * @param user the user to set
	 */
	public final void setUser(User user) {
		this.user = user;
	}
	
	@OneToMany(fetch=FetchType.LAZY, mappedBy="message")
	@Cascade( { org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
	private Set<Message> comments;
	
	@ManyToOne
	@JoinColumn(name="message_parent", nullable = true)
	private Message message;

	/**
	 * @return the comments
	 */
	public final Set<Message> getComments() {
		return comments;
	}

	/**
	 * @param comments the comments to set
	 */
	public final void setComments(Set<Message> comments) {
		this.comments = comments;
	}

	/**
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public final int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((content == null) ? 0 : content.hashCode());
		result = prime * result + id;
		return result;
	}

	/**
	 * @return the message
	 */
	public final Message getMessage() {
		return message;
	}

	/**
	 * @param message the message to set
	 */
	public final void setMessage(Message message) {
		this.message = message;
	}

	/**
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public final boolean equals(Object obj) {
		if (this == obj){
			return true;
		}
		if (obj == null){
			return false;
		}
		if (getClass() != obj.getClass()){
			return false;
		}
		Message other = (Message) obj;
		if (content == null) {
			if (other.content != null){
				return false;
			}
		} else if (!content.equals(other.content)){
			return false;
		}
		if (id != other.id){
			return false;
		}
		return true;
	}

	/**
	 * Set the date.
	 * @param date The date.
	 */
	public final void setDate(Date date) {
		this.date = date;
	}

	/**
	 * Get the date of the message.
	 * @return The date.
	 */
	public final Date getDate() {
		return date;
	}

	/**
	 * Gets the favoriteUsers, i.e. users which have added this message to their favorites messages.
	 * @return the favorite users
	 */
	public final Set<User> getFavoriteUsers() {
		return favoriteUsers;
	}

	/**
	 * Sets the favoriteUsers, i.e. users which have added this message to their favorites messages.
	 * @param favoriteUsers the users to add
	 */
	public final void setFavoriteUsers(Set<User> favoriteUsers) {
		this.favoriteUsers = favoriteUsers;
	}
	
	
	
}
